#ifndef __wBaseClass_H__
#define __wBaseClass_H__

#if !WINDOWS_SYSTEM
	#error only windows system supported
#endif

//////////////////////////////////////////////////////////////////////////
// Class uCTimer
class uCTimer
{
public:
	static double GetTickCount()
	{
		static BOOL bEnable = FALSE;
		static LARGE_INTEGER Freq;
		LARGE_INTEGER T1;
		if(!bEnable)
		{
			QueryPerformanceFrequency(&Freq);
			bEnable = TRUE;
		}
		QueryPerformanceCounter(&T1);
		return T1.QuadPart * 1000.0 / Freq.QuadPart;
//		double dTick = (double)T1.QuadPart * 1000.0 / (double)Freq.QuadPart;
//		return dTick;
	}
};

class wCritSecLock
{
public:
	wCritSecLock()
	{
		::InitializeCriticalSection(&m_objCriSec);
		m_bLocked = false;
	}
	~wCritSecLock()
	{
		chASSERT(!m_bLocked);
		::DeleteCriticalSection(&m_objCriSec);
	}

	void Lock()
	{
		::EnterCriticalSection(&m_objCriSec);
		m_bLocked = true;
	}
	void Unlock()
	{
		chASSERT( m_bLocked );
		m_bLocked = false;
		::LeaveCriticalSection(&m_objCriSec);
	}

// Implementation
private:
	CRITICAL_SECTION		m_objCriSec;
	bool					m_bLocked;

// Private to avoid accidental use
	wCritSecLock( const wCritSecLock& ){}
	wCritSecLock& operator=( const wCritSecLock& ){return *this;}
};

class wMapFile
{
public:
	BOOL CreateMapFile(LPCTSTR lpszFileName, DWORD dwSize)
	{
		chASSERT(m_hFileHandle == NULL && !chIS_EMPTY(lpszFileName));
		m_hFileHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
			dwSize, lpszFileName);
		return m_hFileHandle != NULL;
	}

	LPVOID MapFile()
	{
		chASSERT(m_hFileHandle != NULL);
		m_pMapData = ::MapViewOfFile(m_hFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
		return m_pMapData;
	}

	void UnmapFile()
	{
		chASSERT(m_hFileHandle != NULL && m_pMapData != NULL);
		UnmapViewOfFile(m_pMapData);
		m_pMapData = NULL;
	}

	void DestroyMapFile()
	{
		chASSERT(m_hFileHandle != NULL && m_pMapData == NULL);
		CloseHandle(m_hFileHandle);
		m_hFileHandle = NULL;
	}
	wMapFile()
	{
		m_pMapData = NULL;
		m_hFileHandle = NULL;
	}
protected:
	LPVOID m_pMapData;
	HANDLE m_hFileHandle;
};

class wMutex
{
// Constructor
	HANDLE m_hObject;
public:
	wMutex()
	{
		m_hObject = INVALID_HANDLE_VALUE;
	}
	~wMutex()
	{
		if(m_hObject != INVALID_HANDLE_VALUE)
			CloseHandle(m_hObject);
	}

public:
	BOOL CreateMutex(BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL)
	{
		chASSERT(m_hObject == INVALID_HANDLE_VALUE);
		m_hObject = ::CreateMutex(lpsaAttribute, bInitiallyOwn, lpszName);
		chASSERT(m_hObject != INVALID_HANDLE_VALUE);
		return m_hObject != INVALID_HANDLE_VALUE;
	}
	BOOL Lock(DWORD dwTimeOut = INFINITE)
	{
		chASSERT(m_hObject != INVALID_HANDLE_VALUE);
		return ::WaitForSingleObject(m_hObject, dwTimeOut) == WAIT_OBJECT_0;
	}
	BOOL Unlock()
	{
		chASSERT(m_hObject != INVALID_HANDLE_VALUE);
		return ::ReleaseMutex(m_hObject);
	}
};

#endif //__wBaseClass_H__
